const fs = require('fs');
const parser = require('@babel/parser')
const traverse = require('@babel/traverse').default;
const path = require('path')
const babel = require('@babel/core')

const moduleAnalyser = (filename) => {
    const content = fs.readFileSync(filename, 'utf-8');
    const ast = parser.parse(content, {
        sourceType: 'module'
    })
    // 将 Index.js 依赖的文件的路径 添加到 数组里面
    const dependenics = {}
    traverse(ast, {
        ImportDeclaration({ node }) {
            const dirname = path.dirname(filename)
            const newFile = './' + path.join(dirname, node.source.value)
            dependenics[node.source.value] = newFile
        }
    })
    const { code } = babel.transformFromAst(ast, null, {
        presets: ["@babel/preset-env"]
    })
    return {
        filename,
        dependenics,
        code
    }
}

const makeDependenciesGraph = (entry) => {
    const entryModule = moduleAnalyser(entry)
    const graphArray = [ entryModule ]
    for (let i = 0; i < graphArray.length; i++) {
        const item = graphArray[i]
        const { dependenics } = item
        if (dependenics) {
            for(let j in dependenics) {
                graphArray.push(
                    moduleAnalyser(dependenics[j])
                )
            }
        }
    }
    const graph = {}
    graphArray.forEach(item => {
        graph[item.filename] = {
            dependenics: item.dependenics,
            code: item.code
        }
    })
    return graph
}

const generateCode = (entry) => {
    const graph = JSON.stringify(makeDependenciesGraph(entry))
    return `
        (function(graph) {
            function require(module) {
                function localRequire(relativePath) {
                    return require(graph[module].dependenics[relativePath])
                }
                var exports = {}
                (function(require, exports, code){
                    eval(code)
                })(localRequire, exports, graph[module].code)
                return exports;
            }
            require('${entry}')
        })(${graph})
    `;
}

const code = generateCode('./src/index.js')
console.log(code)
